package com.big.common.mybatis.base.service.impl;

import cn.hutool.core.lang.Assert;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.big.common.core.domain.dto.BaseDTO;
import com.big.common.core.exception.CustomerException;
import com.big.common.core.result.PageQuery;
import com.big.common.core.result.Query;
import com.big.common.core.util.ConditionHandler;
import com.big.common.core.util.ConvertUtil;
import com.big.common.mybatis.base.domain.entity.BaseEntity;
import com.big.common.mybatis.base.mapper.IBaseMapper;
import com.big.common.mybatis.base.service.BaseService;
import com.big.common.mybatis.result.PageResult;
import com.big.common.mybatis.util.MybatisPageUtils;
import com.big.common.mybatis.util.PageQueryWrapper;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.transaction.annotation.Transactional;

import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.List;
import java.util.Optional;

/**
 * <p>
 * 基础服务实现类
 * </p>
 *
 * @author 山归岿
 * @create 2025-06-21-15:06
 */
@Slf4j
@RequiredArgsConstructor
public abstract class BaseServiceImpl<DTO extends BaseDTO, T extends BaseEntity>
        extends ServiceImpl<IBaseMapper<T>, T>
        implements BaseService<DTO, T> {

    // 获取 DTO 类型
    private final Class<DTO> dtoType;

    @SuppressWarnings("unchecked")
    public BaseServiceImpl() {
        // 通过反射获取 DTO 的实际类型
        Type superClass = getClass().getGenericSuperclass();
        if (superClass instanceof ParameterizedType) {
            Type[] types = ((ParameterizedType) superClass).getActualTypeArguments();
            if (types.length > 0 && types[0] instanceof Class<?>) {
                this.dtoType = (Class<DTO>) types[0];
                log.debug("成功解析 DTO 类型: {}", dtoType.getName());
            } else {
                throw new IllegalArgumentException("无法获取有效的 DTO 类型");
            }
        } else {
            throw new IllegalArgumentException("当前类未定义泛型参数");
        }

        Assert.notNull(this.dtoType, "DTO 类型解析失败");
    }

    @Override
    public PageResult<DTO> page(PageQuery<DTO> pageQuery) {
        // 1. 创建查询包装器
        PageQueryWrapper<T, DTO> pageQueryWrapper = PageQueryWrapper.of(pageQuery);

        // 2. 前置处理：允许子类修改查询条件
        beforePageQuery(pageQueryWrapper);

        // 3. 执行分页查询
        Page<T> pageResult = page(pageQueryWrapper.page(), pageQueryWrapper.queryWrapper());

        // 4. 转换DTO结果
        PageResult<T> result = new PageResult<>(pageResult);
        PageResult<DTO> dtoPageResult = result.mapTo(dtoType);

        // 5. 后置处理：允许子类处理转换后的DTO列表
        afterDtoConverted(dtoPageResult.getRecords());
        return dtoPageResult;
    }

    @Override
    public DTO getByIdDTO(String id) {
        // 1. 获取实体
        DTO convert = ConvertUtil.convert(getById(id), dtoType);

        // 2. 后置处理：允许子类处理转换后的实体
        afterEntityInserted(convert);
        return convert;
    }

    @Override
    public List<DTO> listDTO(Query<DTO> query) {
        // 1. 处理排序条件和高级查询
        QueryWrapper<T> queryWrapper = MybatisPageUtils.handleOrderByAndQuery(query);

        // 2. 查询
        beforeAllQuery(queryWrapper, query.getQuery());

        // 3. 转换
        List<DTO> dtoList = ConvertUtil.convertList(list(queryWrapper), dtoType);

        // 4. 添加后置处理
        afterAllEntitiesInserted(dtoList);
        return dtoList;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public String add(DTO dto) {
        return Optional.ofNullable(dto)
                .map(d -> {
                    // 1. 添加前处理
                    beforeAdd(d);

                    // 2. 转换
                    T convert = ConvertUtil.convert(d, getEntityClass());
                    boolean flag = this.save(convert);

                    // 3. 添加后处理
                    ConditionHandler.branchOrThrow(flag, () -> {
                        d.setId(convert.getId());
                        afterAdd(d);
                    }, () -> new CustomerException("新增失败！"));
                    return convert.getId();
                })
                .orElseThrow(() -> new IllegalArgumentException("传入的 DTO 不能为空"));
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean addBatch(List<DTO> entityList, int batchSize) {
        return Optional.ofNullable(entityList)
                .map(list -> {
                    // 1.批量添加前处理
                    beforeBatchAdd(list);

                    // 2.转换
                    List<T> convertList = ConvertUtil.convertList(list, getEntityClass());
                    boolean flag = this.saveBatch(convertList, batchSize);

                    // 3.批量添加后处理
                    ConditionHandler.branchOrThrow(flag, () -> {
                        List<DTO> dtoList = ConvertUtil.convertList(convertList, dtoType);
                        afterBatchAdd(dtoList);
                    }, () -> new RuntimeException("批量新增失败"));
                    return true;
                })
                .orElseThrow(() -> new IllegalArgumentException("传入的 DTO 不能为空"));
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public String update(DTO dto) {
        return Optional.ofNullable(dto)
                .map(d -> {
                    // 1.修改前处理
                    beforeUpdate(d);

                    // 2.转换
                    T convert = ConvertUtil.convert(d, getEntityClass());
                    boolean flag = this.updateById(convert);

                    // 3.修改后置处理
                    ConditionHandler.branchOrThrow(flag, () -> afterUpdate(d), () -> new CustomerException("更新失败！"));
                    return convert.getId();
                })
                .orElseThrow(() -> new IllegalArgumentException("传入的 DTO 不能为空"));
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean updateBatch(List<DTO> entityList, int batchSize) {
        return Optional.ofNullable(entityList)
                .map(list -> {
                    // 1.批量修改前处理
                    beforeBatchUpdate(list);

                    // 2.批量修改
                    List<T> convertList = ConvertUtil.convertList(list, getEntityClass());
                    boolean flag = this.updateBatchById(convertList, batchSize);

                    // 3.批量修改后处理
                    ConditionHandler.branchOrThrow(flag, () -> {
                        List<DTO> dtoList = ConvertUtil.convertList(convertList, dtoType);
                        afterBatchUpdate(dtoList);
                    }, () -> new RuntimeException("更新失败"));
                    return true;
                })
                .orElseThrow(() -> new IllegalArgumentException("传入的 DTO 不能为空"));
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean delete(String id) {
        return Optional.ofNullable(id)
                .map(data -> {
                    // 1.删除前处理
                    beforeDelete(id);

                    // 2.删除
                    boolean flag = this.removeById(id);

                    // 3.删除后处理
                    ConditionHandler.branchOrThrow(flag, () -> afterDelete(id), () -> new RuntimeException("删除失败"));
                    return true;
                })
                .orElseThrow(() -> new IllegalArgumentException("传入的 ID 不能为空"));
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean deleteBatch(List<String> ids) {
        return Optional.ofNullable(ids)
                .map(data -> {
                    // 1.批量删除前处理
                    beforeBatchDelete(ids);

                    // 2.批量删除
                    boolean flag = this.removeByIds(ids);

                    // 3.批量删除后处理
                    ConditionHandler.branchOrThrow(flag, () -> afterBatchDelete(ids), () -> new IllegalArgumentException("删除失败"));
                    return true;
                })
                .orElseThrow(() -> new IllegalArgumentException("传入的 ID 不能为空"));
    }

}
